<?php

namespace common\service;

use support\SingletonTrait;
use common\model\EntityModel;

class EntityUseService
{
    use SingletonTrait;

    /**
     * 角色,道具 使用情况
     * @param $rolePropsEntity
     * @return array
     */
    public function rolePropsUseInfo($rolePropsEntity)
    {

        $projectId = $rolePropsEntity[0]['project_id'] ?? 0;
        $designCodes = array_column($rolePropsEntity, 'code');
        $assetEntityData = model(EntityModel::class)
            ->where(['module_id' => module_by_code('asset')['id'], 'project_id' => $projectId])
            ->where(['code' => ['IN', $designCodes]])
            ->field("id,code,json ->> '$.asset_design' as asset_design")
            ->select();
        if (empty($assetEntityData)) {
            return [];
        }
        // 查出概览生成的资产绑定到一个数组里,方便匹配关联的镜头
        $assetEntityMap = array_column($assetEntityData, null, 'asset_design');
        $rolePropsEntity = array_map(function ($tmp) use ($assetEntityMap) {
            $tmp['asset_design'] = $assetEntityMap[$tmp['id']]['id'] ?? 0;
            return $tmp;
        }, $rolePropsEntity);

        // 通过[角色,道具]找到当前资产下关联的镜头->集
        $assetEntityIds = array_column($assetEntityData, 'id');
        $where = '(';
        foreach ($assetEntityIds as $assetEntityId) {
            $where .= "find_in_set({$assetEntityId},json->>'$.storyboard_asset')";
            $where .= ' OR ';
        }
        $where = trim($where, ' OR');
        $where .= ')';

        $shotData = model(EntityModel::class)
            ->where(['project_id' => $projectId, 'module_id' => module_by_code('storyboard')['id']])
            ->where($where)
            ->field("id,code,project_id,module_id,initial_episode_code,json ->> '$.storyboard_asset' as storyboard_asset")
            ->group('initial_episode_code')
            ->select();
        if (empty($shotData)) {
            return [];
        }
        $shotData = array_map(function ($tmp) {
            if (!empty($tmp['storyboard_asset'])) {
                $tmp['storyboard_asset'] = explode(',', $tmp['storyboard_asset']);
            }
            return $tmp;
        }, $shotData);

        // 计算每个实体关联的镜头数量->角色,道具
        foreach ($rolePropsEntity as &$rolePropsEntityItem) {
            $num = 0;
            foreach ($shotData as $shotDataItem) {
                if (!empty($rolePropsEntityItem['asset_design']) && !empty($shotDataItem['storyboard_asset'])) {
                    if (in_array($rolePropsEntityItem['asset_design'], $shotDataItem['storyboard_asset'])) {
                        $num++;
                    }
                }
            }
            $rolePropsEntityItem['num'] = $num;
            unset($num);
        }
        $returnData = [];
        foreach ($rolePropsEntity as $item) {
            if (empty($item['num'])) {
                continue;
            }
            $returnData["entity-" . $item['id']] = [['type' => 'episode', 'num' => $item['num']]];
            unset($item['num']);
        }
        return $returnData;
    }

    /**
     * 场景 使用情况
     * @param $data
     * @return array
     */
    public function scenarioUseInfo($data)
    {
        // 通过[场景]找到当前资产下关联的关卡
        $projectId = $data[0]['project_id'] ?? 0;
        $where = '(';
        foreach ($data as $scenarioName) {
            $where .= "find_in_set('{$scenarioName['name']}',json->>'$.level_relate_asset')";
            $where .= ' OR ';
        }
        $where = trim($where, ' OR');
        $where .= ')';
        $levelData = model(EntityModel::class)
            ->where(['project_id' => $projectId, 'module_id' => module_by_code('design')['id'], "json->>'$.design_category'" => '关卡'])
            ->where($where)
            ->field("id,code,json->>'$.level_relate_asset' as level_relate_asset")
            ->select();
        $levelData = array_map(function ($tmp) {
            if (!empty($tmp['level_relate_asset'])) {
                $tmp['level_relate_asset'] = explode(',', $tmp['level_relate_asset']);
            }
            return $tmp;
        }, $levelData);
        if (empty($levelData)) {
            return [];
        }
        // 计算每个每个场景下的关卡
        foreach ($data as &$dataItem) {
            $num = 0;
            foreach ($levelData as $levelDataItem) {
                if (!empty($dataItem['name']) && !empty($levelDataItem['level_relate_asset'])) {
                    if (in_array($dataItem['name'], $levelDataItem['level_relate_asset'])) {
                        $num++;
                    }
                }
            }
            $dataItem['num'] = $num;
        }

        $returnData = [];
        foreach ($data as $item) {
            if (empty($item['num'])) {
                continue;
            }
            $returnData["entity-" . $item['id']] = [['type' => 'level', 'num' => $item['num']]];
        }
        return $returnData;
    }

    /**
     * 关卡使用的集
     * @param $entityData
     * @return array
     */
    public function levelEpisodeUseInfo($entityData)
    {
        $projectId = $entityData[0]['project_id'] ?? 0;
        $designCodes = array_column($entityData, 'code');

        $assetEntityData = model(EntityModel::class)
            ->where(['module_id' => module_by_code('level')['id'], 'project_id' => $projectId])
            ->where(['code' => ['IN', $designCodes]])
            ->field("id,code,json ->> '$.level_design' as level_design")
            ->select();
        if (empty($assetEntityData)) {
            return [];
        }

        $assetEntityIds = array_column($assetEntityData, 'id');
        $where = '(';
        foreach ($assetEntityIds as $assetEntityId) {
            $where .= "find_in_set({$assetEntityId},json->>'$.storyboard_level')";
            $where .= ' OR ';
        }
        $where = trim($where, ' OR');
        $where .= ')';
        $shotData = model(EntityModel::class)
            ->where(['project_id' => $projectId, 'module_id' => module_by_code('storyboard')['id']])
            ->where($where)
            ->field("initial_episode_code,json ->> '$.storyboard_level' as storyboard_level")
            ->group("initial_episode_code,json ->> '$.storyboard_level'")
            ->select();
        if (empty($shotData)) {
            return [];
        }
        $levelEpisodeCodeList = [];
        foreach ($shotData as $tmp) {
            if (empty($tmp['storyboard_level'])) {
                continue;
            }
            $tmp['storyboard_level'] = explode(',', trim($tmp['storyboard_level'], ','));
            foreach ($tmp['storyboard_level'] as $storyboardLevelId) {
                $storyboardLevelId = intval($storyboardLevelId);
                if ($storyboardLevelId <= 0) {
                    continue;
                }
                if (!isset($levelEpisodeCodeList[$storyboardLevelId])) {
                    $levelEpisodeCodeList[$storyboardLevelId][] = $tmp['initial_episode_code'];
                } else if (!in_array($tmp['initial_episode_code'], $levelEpisodeCodeList[$storyboardLevelId])) {
                    $levelEpisodeCodeList[$storyboardLevelId][] = $tmp['initial_episode_code'];
                }
            }
        }

        // 计算关卡关联的[集]
        foreach ($assetEntityData as &$assetEntityItem) {
            $episodeCodeList = $levelEpisodeCodeList[$assetEntityItem['id']] ?? [];
            $assetEntityItem['num'] = count($episodeCodeList);
        }
        $returnData = [];
        foreach ($assetEntityData as $item) {
            if (empty($item['num'])) {
                continue;
            }
            $returnData["entity-" . $item['level_design']] = [['type' => 'episode', 'num' => $item['num']]];
        }
        return $returnData;
    }

    /**
     * 关卡使用的场景
     * @param $entityData
     * @return array
     */
    public function levelScenarioUseInfo($entityData)
    {
        // 查询关卡下的场景
        if (empty($entityData)) {
            return [];
        }
        $entityData = array_map(function ($tmp) {
            if (!empty($tmp['level_relate_asset'])) {
                $tmp['level_relate_asset'] = explode(',', trim($tmp['level_relate_asset'], ','));
                $tmp['num'] = count($tmp['level_relate_asset']);
            }
            return $tmp;
        }, $entityData);

        $returnData = [];
        foreach ($entityData as $item) {
            if (empty($item['num'])) {
                continue;
            }
            $returnData["entity-" . $item['id']] = [['type' => 'scenario', 'num' => $item['num']]];
        }
        return $returnData;
    }

    /**
     * 镜头使用情况
     * @return array[]
     */
    public function showUseInfo($entityData)
    {
        if (empty($entityData)) {
            return [];
        }
        $entityData = array_map(function ($tmp) {
            $assetNum = 0;
            $levelNum = 0;
            if (!empty($tmp['storyboard_asset_ids'])) {
                $storyboardAssetIds = explode(',', trim($tmp['storyboard_asset_ids'], ','));
                $assetNum = count($storyboardAssetIds);
            }
            if (!empty($tmp['storyboard_level_ids'])) {
                $storyboardLevelIds = explode(',', trim($tmp['storyboard_level_ids'], ','));
                $levelNum = count($storyboardLevelIds);
            }
            $tmp['num'] = $assetNum + $levelNum;
            return $tmp;
        }, $entityData);
        $returnData = [];
        foreach ($entityData as $item) {
            if (empty($item['num'])) {
                continue;
            }
            $returnData["entity-" . $item['id']] = [['type' => 'asset', 'num' => $item['num']]];
        }
        return $returnData;
    }

    /**
     * 获取实体,镜头使用情况
     * @param $entityIds
     * @return array
     */
    public function getUseInfo($entityIds)
    {
        $entityData = model(EntityModel::class)->join('module on entity.module_id = module.id')
            ->where(['entity.id' => ['IN', $entityIds]])
            ->field("entity.id,entity.json->> '$.storyboard_asset' as storyboard_asset_ids,entity.json ->> '$.storyboard_level' as storyboard_level_ids,entity.module_id,entity.project_id,entity.code,entity.name,module.code as module_code,entity.json->>'$.design_category' as design_category,entity.json ->> '$.level_relate_asset' as level_relate_asset")
            ->select();
        $entityMap = array_group_by($entityData, 'design_category');
        $rolePropsEntity = [];
        if (!empty($entityMap['角色'])) {
            $rolePropsEntity = array_merge($rolePropsEntity, $entityMap['角色']);
        }
        if (!empty($entityMap['道具'])) {
            $rolePropsEntity = array_merge($rolePropsEntity, $entityMap['道具']);
        }
        // 处理[角色]和[道具]关联的[集]
        $rolePropsUseInfo = [];
        if (!empty($rolePropsEntity)) {
            $rolePropsUseInfo = $this->rolePropsUseInfo($rolePropsEntity);
        }
        // 处理场景关联的[关卡]
        $scenarioUseInfo = [];
        if (!empty($entityMap['场景'])) {
            $scenarioUseInfo = $this->scenarioUseInfo($entityMap['场景']);
        }
        $levelScenarioUseInfo = [];
        $levelEpisodeUseInfo = [];
        if (!empty($entityMap['关卡'])) {
            $levelEpisodeUseInfo = $this->levelEpisodeUseInfo($entityMap['关卡']);  // 处理关卡关联的[集]
            $levelScenarioUseInfo = $this->levelScenarioUseInfo($entityMap['关卡']); // 处理关卡关联的[场景]
        }
        // 处理[镜头]关联的[资产]
        $shotUseInfo = [];
        $moduleCodeMap = array_group_by($entityData, 'module_code');
        if (!empty($moduleCodeMap['storyboard'])) {
            $shotUseInfo = $this->showUseInfo($moduleCodeMap['storyboard']);
        }

        $useInfoMap = array_merge_recursive($rolePropsUseInfo, $scenarioUseInfo, $levelScenarioUseInfo, $levelEpisodeUseInfo, $shotUseInfo);
        return array_map(function ($tmp) use ($useInfoMap) {
            $tmp['use_info'] = $useInfoMap["entity-" . $tmp['id']] ?? [];
            unset($tmp['design_category'], $tmp['level_relate_asset'], $tmp['storyboard_asset_ids'], $tmp['storyboard_level_ids']);
            return $tmp;
        }, $entityData);
    }
}
